local skynet  = require "skynet"
local SQL     = require "sql"
local show    = require "showmsg" 
local manager = require "manager"
local mmo     = require "mmo"
local socket  = require "socket" 
local task    = require "db.task"

local start_gold    = 0
local char_account  = 0 -- 不能大于创建角色最大数
local char_sql
local char_table    = "character"

local M  = {}

-- 临时使用的内部创建角色
function M:inter_create(client,fd)

    if not client then 
        return true 
    end 

     if self:make_new_char_sql(client.account_id, client.name, client.slot) < 0 then 
        show:debug("创建角色失败")
     end 

     return false
end 

function M:char_tolist(data)

    local list = {}

    -- 没有要拷贝的角色数据
    if #data < 0 then 

        skynet.error("char_tolist 没有数据")
        return list
    end 

    for _,v in pairs(data) do 

        if type(v) == "table" then 

            local temp = {}

            temp.account_id = v.account_id
            temp.char_id    = v.char_id 
            temp.name       = v.name 
            temp.slot       = v.slot

            list[#list + 1] = temp 
        end 
    end 

    return list
end 

-- 角色列表
function M:char_list(client, fd, response)

    if not fd then 
        return true 
    end 

    -- 获取在线账户
    --local account_manager = skynet.call("global_manager","lua","get", "account_manager")

    local online_char = skynet.call("global_manager", "lua", "mgr_get", "account_manager", fd)
    
    -- 获取该角色数据
    --local online_char = account_manager:get(fd)
    
    if not online_char then 
        show:info("没有该角色存在") 
        return true 
    end 

    if SQL_ERROR == SQL:query(char_sql, "select `account_id`, `char_id`, `name`, `slot` from `%s` where `account_id` = '%d' LIMIT %d ", 
            char_table, online_char.account_id, MAX_CHARS) or SQL_ERROR == SQL:num_rows(char_sql)  then 

        if response then

            -- 没有角色的时候是一张空表 
            socket:send_package(fd, response({list= {}}))
            return false
        end         
    end 

    local charlist = self:char_tolist(char_sql.result)

    if response then 

        socket:send_package(fd, response({list = charlist}))
    end 

    return false    
end 

-- 角色创建
function M:char_create(client, fd, response)

    if not client and not fd then

        return true 
    end 

    if self:make_new_char_sql(client.account_id, client.name, client.slot) < 0 then 
        
        show:warning("创建失败 账户ID = %d 角色名称 = %s 槽位 = %d", client.account_id, client.name, client.slot )
       
        if response then 
            socket:send_package(fd, response({result = 16}))
        end 

        return false 
    end 

    if response then 

        socket:send_package(fd, response({result = 0}))
    end 

    return false
end 

-- 角色删除
function M:char_remove(client, fd, response)
end 

-- 获取对应等级的任务
function M:get_level_quest(lv, quest)

    local list = {}

    for _,v in pairs(quest) do 

        if v.grade == lv then 
            list[#list +1] = v
        end 
    end

    return list     
end 

-- 角色选择
function M:char_pick(client, fd, response)

    if not client or not fd then 

        return true 
    end 
    client = client.pick


    show:info("开始加载 角色数据 char_id = %d, name = %s , slot = %d, account_id = %d ", client.char_id, client.name, client.slot, client.account_id)
    

    local  charstatus = self:create_charstatus(client.char_id)

    if  self:char_fromsql(client.char_id, charstatus) then

        SQL:show_debug(char_sql, "char.lua", "查询失败")
        
        if response then 

            socket:send_package(fd, response({char = {}}))
            return false 
        end  
    end 
    
    -- 保存角色数据
    --char_manager:add(charstatus.account_id, charstatus)
    skynet.call("global_manager", "lua", "mgr_add", "char_manager",charstatus.account_id, charstatus) 

    -- 返回数据
    if response then 
        socket:send_package(fd, response({char = charstatus}))       
    end 

    return false
end 

--退出游戏
function M:do_shutdown()
end 

-- 保存物品数据信息
function M:memitemdata_to_sql(item, max, id, tableswitch)
end 

-- 在线数据清理
function M:online_data_cleanup()
end 

-- 删除请求
function M:char_delect_req()
end 

--删除连接
function M:char_delect_accept()
end 

-- 删除取消
function M:char_delect_cancel()
end 

-- 创建在线角色数据
function M:create_online_char_data(account_id)

    --在线角色结构体
    local online_char_data = {
    account_id          = 0,
    char_id             = -1,
    fd                  = -1,
    waiting_disconnect  = -1,
    server              = -1,
    }

    -- 设置账户ID
    online_char_data.account_id = account_id

    return online_char_data
end 

-- 设置在线
function M:set_char_online(account_id)
end 

-- 设置离线
function M:set_char_offline(char_id, account_id)
end
 
-- 角色数据库设置离线
function M:char_db_setoffline()
end 

-- 角色数据库踢下线
function M:char_db_kickoffline()
end 

-- 设置全部离线
function M:set_all_offline()
end 

-- 设置全部脱机状态
function M:set_all_offline_sql()
end 

-- 创建角色状态
function M:create_charstatus(char_id)

    local charstatus = mmo:create_charstatus()
    charstatus.char_id = char_id
    return charstatus
end 

-- 角色数据写如到sql
function M:tosql()
end 


-- 角色信息读到缓存中
function M:mmo_char_tobuf(charstatus, data)

        if not charstatus or not data then
            return true 
        end  

    charstatus.char_id        = data.char_id
    charstatus.account_id     = data.account_id
    charstatus.slot           = data.slot
    charstatus.name           = data.name
    charstatus.base_level     = data.base_level
    charstatus.base_exp       = data.base_exp
    charstatus.gold           = data.gold 
    charstatus.class          = data.class
    charstatus.max_hp         = data.max_hp
    charstatus.hp             = data.hp 
    charstatus.max_sp         = data.max_sp
    charstatus.sp             = data.sp
    charstatus.quest          = self:get_level_quest(data.base_level, task)

        return false
end 


-- sql 读取角色数据
function M:char_fromsql(char_id, charstatus)

    if not char_id and not charstatus then 
        return true 
    end 

--[[
    if save_log then 
        show:info("角色加载请求 (%d)", char_id)
    end 
]]--
    
    if SQL_ERROR == SQL:query(char_sql, "select * from `%s` where `char_id` = '%d' LIMIT 1", char_table, char_id) or SQL:get_data(char_sql) then 

        SQL:show_debug(char_sql, "char_lua", "查询错误")
        return true 
    end 

    if self:mmo_char_tobuf(charstatus, char_sql.data) then 
        show:debug("获取数据失败")
        return true 
    end 

    return false

--[[
    if save_log then 
        show:info("加载角色(%d - %s): %s", char_id, char_sql.data.name, "加载")
    end
]]-- 
    -- 以下未写
    -- 物品数据
    -- 技能数据
    -- 仓库数据
    -- 好友数据
end 

-- 初始化角色
function M:sql_init()

    show:info("开始初始化")

    -- self:set_all_offline()
    -- 
    show:info("完成初始化")
end 

-- 更改名字
function M:rename_char_sql()
end 

-- 检查名字
function M:check_name(name, esc_name)

    if not name then 

        return -2 
    end 

    if SQL_ERROR == SQL:query(char_sql, "select 1 from `%s` where `name` = '%s'", char_table, name) then 
        return -2  
    end 

    -- 大于0 说明已经存在该名字
    if SQL:num_rows(char_sql)  > 0 then 

        return -1 
    end
    
    return false 
end 


-- 创建一个新角色
function M:make_new_char_sql(account_id, name, slot)

    local flag 

    -- 检查该角色名称是否已经存在
     flag = self:check_name(name)

     if flag ~= false then

        return flag
     end

     -- 创建角色数不能大于最大数
     if slot > MAX_CHARS then 
        return -2
     end 

     -- 如果已经存在角色
    if char_account ~= 0 then 

        if SQL_ERROR == SQL:query(char_sql,"select 1 from `%s` where `account_id` = '%d'", 
            char_table, account_id) then 
           
           SQL:show_debug(char_sql, "char.lua", "查询失败")
        end 

        if SQL:num_rows(char_sql) > char_account then 
           
           return -2
        end 
    end 

    -- 检查该槽位是否已经存在角色
      if SQL_ERROR == SQL:query(char_sql,"select 1 from `%s` where `account_id` = '%s' and `slot` = '%d'", 
            char_table, account_id, slot) then 
         
         SQL:show_debug(char_sql, "char.lua", "查询失败")
         return -2
      end 

      -- 表示该槽位已经在使用
      if SQL:num_rows(char_sql) > 0 then 
        
         return -2
      end 
      
      --[[ 记录创建角色日志
      if log_char then 
      end 
      ]]--
    
    -- 插入角色数据到数据库
      if SQL_ERROR == SQL:query(char_sql, "insert into `%s`(`account_id`, `slot`, `name`, `gold`) value('%d', '%d', '%s', '%d')", 
            char_table, account_id, slot, name, start_gold) then 

         SQL:show_debug(char_sql, "char.lua", "查询失败")
         return -2
      end 

      -- 获取角色ID
      if SQL_ERROR == SQL:insert_id(char_sql, "select `char_id` from `%s` where `account_id` = '%d' and `name` = '%s'", 
            char_table, account_id, name)  then
         
         SQL:show_debug(char_sql, "char.lua", "查询失败")
         return -2
      end

      -- 获取数据
      SQL:get_data(char_sql)

      local char_id = char_sql.data.char_id

      show:info("创建角色: 账户: %d, 角色: %d, 槽位: %d, 名字: %s", account_id, char_id, slot, name)
     
      return char_id
end  

-- 删除角色
function M:delect_char_sql()
end 

-- 返回在线人数
function M:count_users()
end

-- 广播用户数
function M:broadcast_user_count()
end 

-- 添加角色到 在线账户中
function M:send_accounts_tologin()
end 

-- 控制台命令解析
function M:parse_console()
end 

-- 角色配置
function M:char_config_read( file )
end 

-- 初始化
function M:do_init(sql, conf, utf)    

    
    char_sql = sql 

    if SQL:connect_db(char_sql, conf, utf) then 

        show:debug("角色连接数据库失败")
        return true 
    end

        
    char_manager = skynet.call("global_manager","lua","get", "char_manager")
        
    if not char_manager then 
        
        char_manager = manager:new()

        if not char_manager then 

            show:warning("创建 %s 管理器失败", "char_manager")
            return true
        end 

        skynet.call("global_manager", "lua", "add", "char_manager", char_manager)          
        show:debug("创建 char_manager 管理已创建")
    end 

    return false
end 



return M